#include "stdafx.h"
#include "XRadioBoxImpl.h"

#include <Util.h>
#include <UIUtil.h>
#include <DrawUtil.h>

//////////////////////////////////////////////////////////////////////////

static const int g_RadioImageTextInternal = 5;



//////////////////////////////////////////////////////////////////////////

template <class I>
CXRadioBoxImpl<I>::CXRadioBoxImpl()
{
    m_bChecked = FALSE;
    m_bShowImage = TRUE;
    m_bScaleImage = FALSE;
}

template <class I>
CXRadioBoxImpl<I>::~CXRadioBoxImpl()
{
}

//////////////////////////////////////////////////////////////////////////
// IXRadioBox

template <class I>
void CXRadioBoxImpl<I>::put_GroupName(IN LPCTSTR szGroupName)
{
    m_strGroupName = szGroupName;
}

template <class I>
void CXRadioBoxImpl<I>::get_GroupName(OUT BSTR* pbstrGroupName)
{
    ::SysReAllocString(pbstrGroupName, m_strGroupName.GetData());
}

template <class I>
void CXRadioBoxImpl<I>::put_Check(IN BOOL bChecked)
{
    if( (!!m_bChecked) != (!!bChecked))
    {
        m_bChecked = bChecked;

        if(m_pButtonDraw != NULL)
        {
            int nHorzIndex, nVertIndex;
            m_pButtonDraw->get_Index(&nHorzIndex, &nVertIndex);
            m_pButtonDraw->put_Index(nHorzIndex, (int)m_bChecked);
        }

        SyncGroupStatus();
        Invalidate();
    }
}

template <class I>
BOOL CXRadioBoxImpl<I>::get_Check()
{
    return m_bChecked;
}

template <class I>
void CXRadioBoxImpl<I>::put_ScaleImage(IN BOOL bScaleImage)
{
    m_bScaleImage = bScaleImage;
    Invalidate();
}

template <class I>
BOOL CXRadioBoxImpl<I>::get_ScaleImage()
{
    return m_bScaleImage;
}

template <class I>
void CXRadioBoxImpl<I>::put_ShowImage(IN BOOL bShowImage)
{
    if((!!bShowImage) != (!!m_bShowImage))
    {
        m_bShowImage = bShowImage;

        if(m_bShowImage && m_pButtonDraw == NULL)
        {
            if(SUCCEEDED(Util::CreateObject(&m_pButtonDraw)))
            {
                m_pButtonDraw->put_ImagePath(_T("@skin:Common\\radiobutton.png"));
                m_pButtonDraw->put_SubCount(4, 2);
            }
        }
        Invalidate();
    }
}

//////////////////////////////////////////////////////////////////////////
// IXFrame
template <class I>
void CXRadioBoxImpl<I>::GetAutoSize(OUT LPSIZE pAutoSize)
{
    SIZE sizeImage = *pAutoSize;
    NeedImage();

    if(m_bShowImage && m_pButtonDraw != NULL)
    {
            m_pButtonDraw->get_ImageSize(&sizeImage);
    }
    else
    {
            superclass::GetAutoSize(&sizeImage);
    }

    SIZE sizeText = {0};
    if(!m_strText.empty())
    {
        CXFrameImpl<I>::GetAutoSize(&sizeText);
        sizeText.cx += 4;
        sizeText.cy += 4;
    }

    pAutoSize->cx = sizeImage.cx + sizeText.cx + ((sizeText.cx > 0) ? g_RadioImageTextInternal : 0);
    pAutoSize->cy = max(sizeImage.cy, sizeText.cy);
}

template <class I>
void CXRadioBoxImpl<I>::Draw(XCANVAS xCanvas, const RECT& rcDraw)
{
    CXFrameImpl<I>::Draw(xCanvas, rcDraw);

    RECT rcWnd;
    get_WindowRect(&rcWnd);

    HRESULT hResult = S_OK;

    NeedImage();
    if(m_bShowImage && m_pButtonDraw != NULL)
    {
        RECT rcImage = rcWnd;
        if(m_bScaleImage)
        {
            hResult = m_pButtonDraw->Draw(xCanvas, &rcImage);
        }
        else
        {
            SIZE sizeImage;
            m_pButtonDraw->get_ImageSize(&sizeImage);

            rcImage.right = rcImage.left + sizeImage.cx;
            rcImage.bottom = rcImage.top + sizeImage.cy;

            if((rcWnd.bottom - rcWnd.top) > sizeImage.cy)
            {
                int nOffsetVert = ((rcWnd.bottom - rcWnd.top) - sizeImage.cy) / 2;
                ::OffsetRect(&rcImage, 0, nOffsetVert);
            }
            else
            {
                rcImage.bottom = rcWnd.bottom;
                if(sizeImage.cy != 0)
                    rcImage.right =  rcImage.left + (rcImage.bottom - rcImage.top) * sizeImage.cx / sizeImage.cy;
            }

            //         if(TestControlFlags(ESkin_Down))
            //             ::OffsetRect(&rcImage, 1, 1);

            if(sizeImage.cy != 0)
                hResult = m_pButtonDraw->Draw(xCanvas, &rcImage);
            rcWnd.left += (g_RadioImageTextInternal + sizeImage.cx);
        }
    }

    if(!m_strText.empty())
    {
        IXFont* pFont = NULL;
        IXTextEnv* pTextEnv = NULL;

        get_Font(&pFont);
        get_TextEnv(&pTextEnv);

        DrawUtil::XDrawText(xCanvas, m_strText, m_strText.Length(), &rcWnd, pTextEnv, pFont);
    }
}

//////////////////////////////////////////////////////////////////////////
// IXBaseObj
template <class I>
void CXRadioBoxImpl<I>::OnConstruct()
{
    superclass::OnConstruct();
    IXTextEnv* pTextEnv = UIUtil::XGetTextEnv(this);
    DWORD dwFlags = pTextEnv->get_DrawFlags();
    pTextEnv->put_DrawFlags(dwFlags & (~DT_CENTER));
}

template <class I>
void CXRadioBoxImpl<I>::NeedImage()
{
    if(!m_bShowImage)
        return;

    if(m_pButtonDraw == NULL)
    {
        if(SUCCEEDED(Util::CreateObject(&m_pButtonDraw)))
        {
            m_pButtonDraw->put_ImagePath(_T("@skin:Common\\radiobutton.png"));
            m_pButtonDraw->put_SubCount(4, 2);
        }
    }
}

// CXFrameImpl
template <class I>
BOOL CXRadioBoxImpl<I>::OnClicked(const POINT* pt)
{
    if(!m_bChecked)
    {
        m_bChecked = !m_bChecked;

        if(m_pButtonDraw != NULL)
        {
            int nHorzIndex, nVertIndex;
            m_pButtonDraw->get_Index(&nHorzIndex, &nVertIndex);
            m_pButtonDraw->put_Index(nHorzIndex, (int)m_bChecked);
        }

        Invalidate();

        SyncGroupStatus();
    }
    superclass::OnClicked(pt);
    return TRUE;
}

struct SyncGroupStatusParam
{
    IXRadioBox*     pSrcBox;
    XString         strSrcGroupName;
    XBSTR        bstrTemp;
};

__inline BOOL SyncGroupStatusCallback(IXControl* pChild, LPARAM lParam)
{
    SyncGroupStatusParam* pParam = (SyncGroupStatusParam*)lParam;
    XQIPtr<IXRadioBox> pRadioBox = pChild;
    if(pRadioBox != NULL && pRadioBox != pParam->pSrcBox)
    {
        if(pRadioBox->get_Check())
        {
            pRadioBox->get_GroupName(&pParam->bstrTemp);
            if(pParam->strSrcGroupName == pParam->bstrTemp)
            {
                pRadioBox->put_Check(FALSE);
            }
        }
    }
    return TRUE;
}

template <class I>
void CXRadioBoxImpl<I>::SyncGroupStatus()
{
    if(!m_bChecked)
        return;

    if(m_strGroupName == _T(""))
        return;

    IXFrame* pFrame = UIUtil::XGetParent(this);

    SyncGroupStatusParam param = {this, m_strGroupName};
    pFrame->TransverseChilds(SyncGroupStatusCallback, (LPARAM)&param);
}

// CXCheckBoxImpl
template <class I>
void CXRadioBoxImpl<I>::OnImageChanged()
{
    if(m_pButtonDraw != NULL)
    {
        int nHorzIndex, nVertIndex;
        m_pButtonDraw->get_Index(&nHorzIndex, &nVertIndex);
        m_pButtonDraw->put_Index(nHorzIndex, (int)m_bChecked);
    }
}
